"""
Base Model
==========

Base model class with common functionality for all database models.
Provides timestamp fields and serialization methods.
"""

from datetime import datetime
from typing import Dict, Any, Optional
from sqlalchemy import Column, DateTime, Integer
from sqlalchemy.ext.declarative import declarative_base
from flask_sqlalchemy import SQLAlchemy

# Create declarative base
Base = declarative_base()

class BaseModel(Base):
    """
    Base model class with common fields and methods.
    
    Provides:
    - Auto-timestamp fields (created_at, updated_at)
    - Serialization methods
    - Common query utilities
    """
    
    __abstract__ = True
    
    # Primary key
    id = Column(Integer, primary_key=True, autoincrement=True)
    
    # Timestamp fields
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
    updated_at = Column(DateTime, default=datetime.utcnow, 
                       onupdate=datetime.utcnow, nullable=False)
    
    def to_dict(self, exclude_fields: Optional[list] = None) -> Dict[str, Any]:
        """
        Convert model instance to dictionary.
        
        Args:
            exclude_fields: List of field names to exclude
        
        Returns:
            Dictionary representation of the model
        """
        if exclude_fields is None:
            exclude_fields = []
        
        result = {}
        for column in self.__table__.columns:
            if column.name not in exclude_fields:
                value = getattr(self, column.name)
                if isinstance(value, datetime):
                    value = value.isoformat()
                result[column.name] = value
        
        return result
    
    def to_json(self, exclude_fields: Optional[list] = None) -> str:
        """
        Convert model instance to JSON string.
        
        Args:
            exclude_fields: List of field names to exclude
        
        Returns:
            JSON string representation
        """
        import json
        return json.dumps(self.to_dict(exclude_fields))
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'BaseModel':
        """
        Create model instance from dictionary.
        
        Args:
            data: Dictionary with model data
        
        Returns:
            Model instance
        """
        instance = cls()
        for key, value in data.items():
            if hasattr(instance, key):
                setattr(instance, key, value)
        return instance
    
    def update_from_dict(self, data: Dict[str, Any], 
                        exclude_fields: Optional[list] = None) -> None:
        """
        Update model instance from dictionary.
        
        Args:
            data: Dictionary with updated data
            exclude_fields: List of field names to exclude from update
        """
        if exclude_fields is None:
            exclude_fields = ['id', 'created_at']
        
        for key, value in data.items():
            if hasattr(self, key) and key not in exclude_fields:
                setattr(self, key, value)
    
    def __repr__(self) -> str:
        """
        String representation of the model.
        
        Returns:
            String representation
        """
        return f"<{self.__class__.__name__}(id={self.id})>"
    
    def __str__(self) -> str:
        """
        String representation of the model.
        
        Returns:
            String representation
        """
        return self.__repr__()